// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
#include "Exception.h"

using namespace std;

#include "Symbole.h"
#include "Valeur.h"

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

class Noeud {
    // classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
    // Remarque : la classe ne contient aucun constructeur
public:
    virtual Valeur* getValeur() = 0; // méthode pure (non implémentée) qui rend la classe abstraite

    virtual void afficher(unsigned short indentation = 0) {
        cout << setw(4 * indentation) << " ";
    }
    // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    virtual void afficherEnC(unsigned short indentation = 0) {
        indentation = indentation;
    } // affiche la traduction du languade en C

    virtual ~Noeud() {
    } // présence d'un destructeur virtuel conseillée dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////

class NoeudSeqInst : public Noeud {
    // classe pour représenter un noeud "sequence d'instruction"
    // qui a autant de fils que d'instructions dans la séquence
public:
    NoeudSeqInst(); // construit une séquence d'instruction vide

    ~NoeudSeqInst() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation = 0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction); // ajoute une instruction à la séquence
    void afficherEnC(unsigned short indentation = 0);
private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////

class NoeudAffectation : public Noeud {
    // classe pour représenter un noeud "affectation"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation

    ~NoeudAffectation() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation = 0); // affiche l'affectation
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
private:
    Noeud* variable;
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudOperateurBinaire : public Noeud {
    // classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
    // et de 2 fils : l'opérande gauche et l'opérande droit
public:
    NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
    // construit une opération binaire : operandeGauche operateur OperandeDroit

    ~NoeudOperateurBinaire() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur

    Noeud* getOpGauche() {
        return operandeGauche;
    };

    Noeud* getOpDroit() {
        return operandeDroit;
    };
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
private:
    Symbole operateur;
    Noeud* operandeGauche;
    Noeud* operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstSi : public Noeud {
    // classe pour représenter un noeud "instruction si" composé de la séquence suivante :
    //    si (<expBool>) <seqInst> { sinonsi (<expBool>) <seqInst> } [ sinon <seqInst> ] finsi
public:
    NoeudInstSi(Noeud* expBool, Noeud* seqInst, Noeud* sinon);
    // construit une instruction si : expBool seqInst sinon

    ~NoeudInstSi() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
    void setSinon(Noeud* sinon); // l'attribut sinon prend pour valeur sinon
    Noeud* getSinon(); // retourne le pointeur sinon
    Noeud* getExp(); //retourne l'expression booléenne du premier si
    Noeud* getSeq(); //retourne l'expression booléenne du premier si
private:
    Noeud* expBool;
    Noeud* seqInst;
    Noeud* sinon;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudBoucle : public Noeud {
    //Classe pour représenter un noeud "boucle"
public:
    NoeudBoucle(Noeud* expBool, Noeud* seqInst);
    // construit une instruction boucle.

    ~NoeudBoucle() {
    } // à cause du destructeur virtuel de la classe Noeud
protected:
    Noeud* expBool;
    Noeud* seqInst;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstTq : public NoeudBoucle {
    //Classe pour représenter un noeud "Tanque" composé de la séquence suivante :
    //<instTq> ::= tantque (<expBool>) <seqInst> fintantque
public:
    NoeudInstTq(Noeud* expBool, Noeud* seqInst);
    // construit une instruction tant que.

    ~NoeudInstTq() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstRepeter : public NoeudBoucle {
    //Classe pour représenter un noeud "Repeter" composé de la séquence suivante :
    //<instRepeter> ::= repeter <seqInst> jusqua (<expBool>)
public:
    NoeudInstRepeter(Noeud* expBool, Noeud* seqInst);
    // construit une instruction repeter.

    ~NoeudInstRepeter() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstPour : public NoeudBoucle {
    //Classe pour représenter un noeud "Pour" composé de la séquence suivante :
    //<instPour> ::= pour ( <affectation> ; <expBool> ; <affectation>) <seqInst> finpour
public:
    NoeudInstPour(Noeud* expBool, Noeud* seqInst, Noeud* affectation1, Noeud* affectation2);
    // construit une instruction pour.

    ~NoeudInstPour() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
protected:
    Noeud* affectation1;
    Noeud* affectation2;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstLire : public Noeud {
    //Classe pour représenter un noeud "Lire" composé de la séquence suivante :
    //<instLire> ::= lire ( <variable> )
public:
    NoeudInstLire(Noeud* variable);
    // construit une instruction Lire.

    ~NoeudInstLire() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
private:
    Noeud* variable;
};


////////////////////////////////////////////////////////////////////////////////

class NoeudInstEcrire : public Noeud {
    //Classe pour représenter un noeud "Ecrire" composé de la séquence suivante :
    //<instEcrire> ::= ecrire ( <expression> | <chaine> )
public:
    NoeudInstEcrire(Noeud* exp);
    // construit une instruction Ecrire.

    ~NoeudInstEcrire() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
private:
    Noeud* exp;
};

////////////////////////////////////////////////////////////////////////////////

class NoeudInstSelon : public Noeud {
    //Classe pour représenter un noeud "Selon" composé de la séquence suivante :
    // <instSelon> ::= selon ( <expression> | <CHAINE> ) cas (<expression> | <CHAINE> ) : <seqInst> 
    // { cas (<expression> | <CHAINE>) : <seqInst> } finselon
public:
    NoeudInstSelon(NoeudInstSi* instsi);
    // construit une instruction selon.

    ~NoeudInstSelon() {
    } // à cause du destructeur virtuel de la classe Noeud
    Valeur* getValeur();
    void afficher(unsigned short indentation = 0); // affiche l'opération
    void afficherEnC(unsigned short indentation = 0); // affiche la traduction du languade en C
private:
    NoeudInstSi* instsi;
};

////////////////////////////////////////////////////////////////////////////////

#endif /* ARBRE_H_ */
